Skip to content

Add basic tracing functionality to tests - #525

Draft
contificate wants to merge 2 commits into
xcp-ng:masterfrom
contificate:cbarr/tracing
Draft

Add basic tracing functionality to tests#525
contificate wants to merge 2 commits into
xcp-ng:masterfrom
contificate:cbarr/tracing

Conversation

@contificate

Copy link
Copy Markdown

Opening as a draft to receive commentary.


This simple change introduces a --tracing-endpoint option to the test framework that, if provided, will augment the host setup fixture to create an observer on each host. The effect of this is that toolstack operations will be traced, with their spans submitted to the provided endpoint (either Zipkin, Jaeger, or compatible span aggregator).


A simple test is provided that uses this to perform an operation and then query the endpoint to fetch the root span of the operation (with some metadata attached).

image

The overall idea is that the benchmarking/performance teams can modify extant tests (or write new tests) to retrofit tracing (in a non-intrusive, opt-in, way).

I'm seeking some feedback about the direction of this change as there's more to consider:

  • Tests with complex pool steps may want to have better identifying metadata by default. So, you can run a test and immediately place the separate hosts' span timeline together for debugging.
  • The Host object's xe method could be modified to allow for environmental variables. Then, as done in the provided sample test (albeit manually), we could supply BAGGAGE to attach metadata to the spans of specific toolstack operations (relying on the metadata to fetch and process the related spans later).

Any feedback will be much appreciated. This change is very simple and could do with being made a lot more featureful and robust, but I'm not overly familiar with the testing framework or its tests, so I've kept it small and isolated for now.

@glehmann

Copy link
Copy Markdown
Member

I like the idea a lot!

Can we attach arbitrary metadata to the spans?
I'd love to have the current test identifier attached to the span—i.e. tests/storage/nfs/test_nfs_sr_intrapool_migration.py::Test::test_live_intrapool_shared_migration[None-vhd-vm_on_nfs4_sr]

@contificate

Copy link
Copy Markdown
Author

Can we attach arbitrary metadata to the spans?

Yes, in the form of baggage. As mentioned in the PR description, a good idea would be to allow passing the BAGGAGE="foo=bar;baz=foo" environment variable to xe in the Host object. Then, certain operations can easily be identified after a test run (or we could write a custom span aggregator that discards things it doesn't care about, with some XQuery-like DSL as part of the test output).

Signed-off-by: Colin James <contificate@gmail.com>
Signed-off-by: Colin James <contificate@gmail.com>
@contificate
contificate marked this pull request as ready for review May 15, 2026 11:49
@contificate
contificate requested a review from a team as a code owner May 15, 2026 11:50
Comment thread conftest.py

tracing_endpoint = pytestconfig.getoption("--tracing-endpoint")
has_tracing = tracing_endpoint is not None
observers = []

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's just one observer per host, right? So rather than maintaining a list of observers, I think each host should have its optional observer as an attribute, and maybe the setup and teardown parts should be handled directly in setup_host and cleanup_hosts.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can have several observers per host with different endpoint for example.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can, but that's not what's in the current implementation, and I suppose that if/when we need more than one observer per host we can have a list or dict of observers attached to the host.

@LuKP17 LuKP17 Jun 10, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my understanding of the relationship between observers and hosts, it's the other way around: observers contain an optional list of hosts uuids. If this list is empty then the observer is pool-wide, we provide hosts uuids if we need to filter which hosts in the pool are affected by this observer (most importantly it dictates which ones are not).
So for migration tests with a pool of 2 hosts, there's no need to specify hosts when creating an observer, we will get the source and dest hosts traces by default (pool-wide observer). But for some tests we would maybe like only one host to be affected by the observer, then add this host's uuid in the observer's host list.
If an observer is a standalone XAPI object, maybe we can rethink how to reflect this in xcp-ng-tests (like introducing an Observer class).

Comment thread conftest.py
logging.info(f'Disabling tracing on {host}')
host.xe('observer-destroy', {'uuid': observer})
host.ssh('rm -f /etc/xapi.conf.d/observer.conf')
host.restart_toolstack(verify=True)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these could be added as methods of the Host object.

Comment thread conftest.py
"--tracing-endpoint",
action="store",
default=None,
help="Specify distributed tracing endpoint."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add examples of endpoints here for users?

Comment thread conftest.py
logging.info(f'Enabling tracing on {host}, endpoint = {endpoint}')
host.ssh('printf "observer-endpoint-http-enabled=true\nobserver-experimental-components=\\"\\"\n" > /etc/xapi.conf.d/observer.conf')
host.restart_toolstack(verify=True)
observer_uuid = host.xe('observer-create', {'name-label': 'xcpng-test', 'endpoints': endpoint, 'enabled': 'true'})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't provide the host's uuid in host-uuids param, we will end up with multiple pool-wide observers if the function is called multiple times, which is not what was intended here I think.

@LuKP17 LuKP17 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there is interest in this PR and we would like to have tracing support for the live migration benchmarking project, we agreed with Colin to reorganize the code into a proper solution. I will open my own PR when I'm done, which will surely introduce an Observer class in /lib as mentioned in one of my comments.

@LuKP17
LuKP17 marked this pull request as draft June 11, 2026 15:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants